import { Injectable } from '@nestjs/common';
import { PrismaService } from 'nestjs-prisma';
import {
  AddSysAreaDto,
  GetSysAreaListDto,
  UpdateSysAreaDto,
} from './dto/req-sys-area.dto';
import { ApiException } from 'src/common/exceptions/api.exception';
import { DataScope } from 'src/common/type/data-scope.type';

@Injectable()
export class SysAreaService {
  constructor(private readonly prisma: PrismaService) { }

  /* 获取所有启用的地区列表（小程序端使用） */
  async enabledList() {
    return await this.prisma.sysArea.findMany({
      where: {
        status: '0',  // 0表示启用
        delFlag: '0'
      },
      orderBy: {
        orderNum: 'asc',
      },
      select: {
        areaId: true,
        areaName: true,
        parentId: true,
        ancestors: true
      }
    });
  }

  /* 列表查询 */
  async list(getSysAreaListDto: GetSysAreaListDto, dataScope: DataScope) {
    const { areaName, status, module } = getSysAreaListDto;
    return await this.prisma.sysArea.findMany({
      orderBy: {
        orderNum: 'asc',
      },
      where: {
        AND: {
          status: module ? status : '0',
          delFlag: '0',
          areaName: {
            contains: areaName,
          },
          OR: dataScope.OR,
        },
      },
    });
  }

  /* 查询这个id之外的地区 */
  async listExclude(areaId: number) {
    return await this.prisma.sysArea.findMany({
      where: {
        delFlag: '0',
        ancestors: {
          not: {
            contains: `,${areaId},`,
          },
        },
      },
    });
  }

  /* 新增 */
  async add(addSysAreaDto: AddSysAreaDto) {
    const { parentId } = addSysAreaDto;
    // 确保parentId是有效的数字
    const validParentId = parentId || 0;

    // 声明在事务外部以便后续使用
    let parentArea = null;
    let ancestors = '0';

    const area = await this.prisma.$transaction(async (prisma) => {
      if (validParentId === 0) {
        // 如果是顶级地区，不需要查询父地区
        return await prisma.sysArea.create({
          data: {
            ...addSysAreaDto,
            parentId: null, // 将顶级地区的parentId设为null而不是0，避免外键约束错误
            ancestors: ancestors, // 顶级地区的ancestors初始化为逗号
          },
        });
      }

      // 查询父地区
      parentArea = await prisma.sysArea.findUnique({
        where: {
          areaId: validParentId,
        },
      });

      if (!parentArea) throw new ApiException('上级地区不存在，请重新选择！');

      // 保存父地区的ancestors用于后续更新
      ancestors = parentArea.ancestors;

      return await prisma.sysArea.create({
        data: {
          ...addSysAreaDto,
          parentId: validParentId,
        },
      });
    });

    // 只有非顶级地区才需要更新ancestors
    if (validParentId !== 0) {
      await this.prisma.sysArea.update({
        where: { areaId: area.areaId },
        data: {
          ancestors: ancestors + area.areaId + ',',
        },
      });
    }
  }

  /* 通过id查询 */
  async oneByAreaId(areaId: number) {
    return await this.prisma.sysArea.findUnique({
      where: {
        areaId,
      },
    });
  }

  /* 更新 */
  async update(updateSysAreaDto: UpdateSysAreaDto) {
    return await this.prisma.$transaction(async (prisma) => {
      const { areaId } = updateSysAreaDto;
      const area = await prisma.sysArea.findUnique({
        where: {
          areaId,
        },
      });
      if (!area) throw new ApiException('该记录不存在，请重新查询后操作。');
      const { parentId } = updateSysAreaDto;
      let parentArea = null;
      // 确保parentId是有效的数字
      const validParentId = parentId || 0;

      if (validParentId === 0) {
        // 如果是根地区，ancestors直接设置为,areaId,
        updateSysAreaDto.ancestors = areaId + '';
        // 将parentId设置为null而不是0，避免外键约束错误
        updateSysAreaDto.parentId = 0;
      } else {
        parentArea = await prisma.sysArea.findUnique({
          where: {
            areaId: validParentId,
          },
        });
        if (!parentArea) throw new ApiException('上级地区不存在，请重新选择。');
        updateSysAreaDto.ancestors = parentArea.ancestors + ',' + areaId;
      }
      return await prisma.sysArea.update({
        data: updateSysAreaDto,
        where: {
          areaId,
        },
      });
    });
  }

  /* 删除 */
  async delete(areaId: number) {
    return await this.prisma.$transaction(async (prisma) => {
      const area = await prisma.sysArea.findUnique({
        include: {
          childArea: true,
        },
        where: {
          areaId,
        },
      });
      if (!area) throw new ApiException('该地区不存在，请刷新后重试。');
      if (area && area.childArea && area.childArea.length)
        throw new ApiException('该地区下存在其他子地区，无法删除');
      await prisma.sysArea.update({
        data: { delFlag: '1' },
        where: {
          areaId,
        },
      });
    });
  }
}